home *** CD-ROM | disk | FTP | other *** search
/ Nautilus 1992 July / Nautilus-3-8 / Nautilus-3-8.bin / Tools & Utilities / Techy Stuff / Development Environments ƒ / Perl 4.0.2 ƒ / cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-05  |  30.2 KB  |  1,303 lines

  1. /* $RCSfile: cmd.c,v $$Revision: 4.0.1.4 $$Date: 91/11/11 16:29:33 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    cmd.c,v $
  9.  * Revision 4.0.1.4  91/11/11  16:29:33  lwall
  10.  * patch19: do {$foo ne "bar";} returned wrong value
  11.  * patch19: some earlier patches weren't propagated to alternate 286 code
  12.  * 
  13.  * Revision 4.0.1.3  91/11/05  16:07:43  lwall
  14.  * patch11: random cleanup
  15.  * patch11: "foo\0" eq "foo" was sometimes optimized to true
  16.  * patch11: foreach on null list could spring memory leak
  17.  * 
  18.  * Revision 4.0.1.2  91/06/07  10:26:45  lwall
  19.  * patch4: new copyright notice
  20.  * patch4: made some allowances for "semi-standard" C
  21.  * 
  22.  * Revision 4.0.1.1  91/04/11  17:36:16  lwall
  23.  * patch1: you may now use "die" and "caller" in a signal handler
  24.  * 
  25.  * Revision 4.0  91/03/20  01:04:18  lwall
  26.  * 4.0 baseline.
  27.  * 
  28.  */
  29.  
  30. #include "EXTERN.h"
  31. #include "perl.h"
  32.  
  33. #ifdef I_VARARGS
  34. #  include <varargs.h>
  35. #endif
  36.  
  37. static STR str_chop;
  38.  
  39. void grow_dlevel();
  40.  
  41. /* do longjmps() clobber register variables? */
  42.  
  43. #if defined(cray) || defined(STDMAC)
  44. #define JMPCLOBBER
  45. #endif
  46.  
  47. /* This is the main command loop.  We try to spend as much time in this loop
  48.  * as possible, so lots of optimizations do their activities in here.  This
  49.  * means things get a little sloppy.
  50.  */
  51.  
  52. int
  53. cmd_exec(cmdparm,gimme,sp)
  54. CMD *VOLATILE cmdparm;
  55. VOLATILE int gimme;
  56. VOLATILE int sp;
  57. {
  58.     register CMD *cmd = cmdparm;
  59.     SPAT *VOLATILE oldspat;
  60.     VOLATILE int firstsave = savestack->ary_fill;
  61.     VOLATILE int oldsave;
  62.     VOLATILE int aryoptsave;
  63. #ifdef DEBUGGING
  64.     VOLATILE int olddlevel;
  65.     VOLATILE int entdlevel;
  66. #endif
  67.     register STR *retstr = &str_undef;
  68.     register char *tmps;
  69.     register int cmdflags;
  70.     register int match;
  71.     register char *go_to = goto_targ;
  72.     register int newsp = -2;
  73.     register STR **st = stack->ary_array;
  74.     FILE *VOLATILE fp;
  75.     ARRAY *VOLATILE ar;
  76.  
  77.     lastsize = 0;
  78. #ifdef DEBUGGING
  79.     entdlevel = dlevel;
  80. #endif
  81. tail_recursion_entry:
  82.  
  83. #ifdef macintosh
  84.     SpinPerlCursor(1);
  85. #endif
  86.  
  87. #ifdef DEBUGGING
  88.     dlevel = entdlevel;
  89. #endif
  90. #ifdef TAINT
  91.     tainted = 0;    /* Each statement is presumed innocent */
  92. #endif
  93.     if (cmd == Nullcmd) {
  94.     if (gimme == G_ARRAY && newsp > -2)
  95.         return newsp;
  96.     else {
  97.         st[++sp] = retstr;
  98.         return sp;
  99.     }
  100.     }
  101.     cmdflags = cmd->c_flags;    /* hopefully load register */
  102.     if (go_to) {
  103.     if (cmd->c_label && strEQ(go_to,cmd->c_label))
  104.         goto_targ = go_to = Nullch;        /* here at last */
  105.     else {
  106.  
  107. #ifdef macintosh
  108.     SpinPerlCursor(1);
  109. #endif
  110.  
  111.         switch (cmd->c_type) {
  112.         case C_IF:
  113.         oldspat = curspat;
  114.         oldsave = savestack->ary_fill;
  115. #ifdef DEBUGGING
  116.         olddlevel = dlevel;
  117. #endif
  118.         retstr = &str_yes;
  119.         newsp = -2;
  120.         if (cmd->ucmd.ccmd.cc_true) {
  121. #ifdef DEBUGGING
  122.             if (debug) {
  123.             debname[dlevel] = 't';
  124.             debdelim[dlevel] = '_';
  125.             if (++dlevel >= dlmax)
  126.                 grow_dlevel();
  127.             }
  128. #endif
  129.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  130.             st = stack->ary_array;    /* possibly reallocated */
  131.             retstr = st[newsp];
  132.         }
  133.         if (!goto_targ)
  134.             go_to = Nullch;
  135.         curspat = oldspat;
  136.         if (savestack->ary_fill > oldsave)
  137.             restorelist(oldsave);
  138. #ifdef DEBUGGING
  139.         dlevel = olddlevel;
  140. #endif
  141.         cmd = cmd->ucmd.ccmd.cc_alt;
  142.         goto tail_recursion_entry;
  143.         case C_ELSE:
  144.         oldspat = curspat;
  145.         oldsave = savestack->ary_fill;
  146. #ifdef DEBUGGING
  147.         olddlevel = dlevel;
  148. #endif
  149.         retstr = &str_undef;
  150.         newsp = -2;
  151.         if (cmd->ucmd.ccmd.cc_true) {
  152. #ifdef DEBUGGING
  153.             if (debug) {
  154.             debname[dlevel] = 'e';
  155.             debdelim[dlevel] = '_';
  156.             if (++dlevel >= dlmax)
  157.                 grow_dlevel();
  158.             }
  159. #endif
  160.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  161.             st = stack->ary_array;    /* possibly reallocated */
  162.             retstr = st[newsp];
  163.         }
  164.         if (!goto_targ)
  165.             go_to = Nullch;
  166.         curspat = oldspat;
  167.         if (savestack->ary_fill > oldsave)
  168.             restorelist(oldsave);
  169. #ifdef DEBUGGING
  170.         dlevel = olddlevel;
  171. #endif
  172.         break;
  173.         case C_BLOCK:
  174.         case C_WHILE:
  175.         if (!(cmdflags & CF_ONCE)) {
  176.             cmdflags |= CF_ONCE;
  177.             if (++loop_ptr >= loop_max) {
  178.             loop_max += 128;
  179.             Renew(loop_stack, loop_max, struct loop);
  180.             }
  181.             loop_stack[loop_ptr].loop_label = cmd->c_label;
  182.             loop_stack[loop_ptr].loop_sp = sp;
  183. #ifdef DEBUGGING
  184.             if (debug & 4) {
  185.             deb("(Pushing label #%d %s)\n",
  186.               loop_ptr, cmd->c_label ? cmd->c_label : "");
  187.             }
  188. #endif
  189.         }
  190. #ifdef JMPCLOBBER
  191.         cmdparm = cmd;
  192. #endif
  193.         match = setjmp(loop_stack[loop_ptr].loop_env);
  194.         if (match) {
  195.             st = stack->ary_array;    /* possibly reallocated */
  196. #ifdef JMPCLOBBER
  197.             cmd = cmdparm;
  198.             cmdflags = cmd->c_flags|CF_ONCE;
  199. #endif
  200.             if (savestack->ary_fill > oldsave)
  201.             restorelist(oldsave);
  202.             switch (match) {
  203.             default:
  204.             fatal("longjmp returned bad value (%d)",match);
  205.             case O_LAST:    /* not done unless go_to found */
  206.             go_to = Nullch;
  207.             if (lastretstr) {
  208.                 retstr = lastretstr;
  209.                 newsp = -2;
  210.             }
  211.             else {
  212.                 newsp = sp + lastsize;
  213.                 retstr = st[newsp];
  214.             }
  215. #ifdef DEBUGGING
  216.             olddlevel = dlevel;
  217. #endif
  218.             curspat = oldspat;
  219.             goto next_cmd;
  220.             case O_NEXT:    /* not done unless go_to found */
  221.             go_to = Nullch;
  222. #ifdef JMPCLOBBER
  223.             newsp = -2;
  224.             retstr = &str_undef;
  225. #endif
  226.             goto next_iter;
  227.             case O_REDO:    /* not done unless go_to found */
  228.             go_to = Nullch;
  229. #ifdef JMPCLOBBER
  230.             newsp = -2;
  231.             retstr = &str_undef;
  232. #endif
  233.             goto doit;
  234.             }
  235.         }
  236.         oldspat = curspat;
  237.         oldsave = savestack->ary_fill;
  238. #ifdef DEBUGGING
  239.         olddlevel = dlevel;
  240. #endif
  241.         if (cmd->ucmd.ccmd.cc_true) {
  242. #ifdef DEBUGGING
  243.             if (debug) {
  244.             debname[dlevel] = 't';
  245.             debdelim[dlevel] = '_';
  246.             if (++dlevel >= dlmax)
  247.                 grow_dlevel();
  248.             }
  249. #endif
  250.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  251.             st = stack->ary_array;    /* possibly reallocated */
  252.             if (newsp >= 0)
  253.             retstr = st[newsp];
  254.         }
  255.         if (!goto_targ) {
  256.             go_to = Nullch;
  257.             goto next_iter;
  258.         }
  259. #ifdef DEBUGGING
  260.         dlevel = olddlevel;
  261. #endif
  262.         if (cmd->ucmd.ccmd.cc_alt) {
  263. #ifdef DEBUGGING
  264.             if (debug) {
  265.             debname[dlevel] = 'a';
  266.             debdelim[dlevel] = '_';
  267.             if (++dlevel >= dlmax)
  268.                 grow_dlevel();
  269.             }
  270. #endif
  271.             newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
  272.             st = stack->ary_array;    /* possibly reallocated */
  273.             if (newsp >= 0)
  274.             retstr = st[newsp];
  275.         }
  276.         if (goto_targ)
  277.             break;
  278.         go_to = Nullch;
  279.         goto finish_while;
  280.         }
  281.         cmd = cmd->c_next;
  282.         if (cmd && cmd->c_head == cmd)
  283.                     /* reached end of while loop */
  284.         return sp;        /* targ isn't in this block */
  285.         if (cmdflags & CF_ONCE) {
  286. #ifdef DEBUGGING
  287.         if (debug & 4) {
  288.             tmps = loop_stack[loop_ptr].loop_label;
  289.             deb("(Popping label #%d %s)\n",loop_ptr,
  290.             tmps ? tmps : "" );
  291.         }
  292. #endif
  293.         loop_ptr--;
  294.         }
  295.         goto tail_recursion_entry;
  296.     }
  297.     }
  298.  
  299. until_loop:
  300.  
  301. #ifdef macintosh
  302.     SpinPerlCursor(1);
  303. #endif
  304.  
  305.     /* Set line number so run-time errors can be located */
  306.  
  307.     curcmd = cmd;
  308.  
  309. #ifdef DEBUGGING
  310.     if (debug) {
  311.     if (debug & 2) {
  312.         deb("%s    (%lx)    r%lx    t%lx    a%lx    n%lx    cs%lx\n",
  313.         cmdname[cmd->c_type],cmd,cmd->c_expr,
  314.         cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt,cmd->c_next,
  315.         curspat);
  316.     }
  317.     debname[dlevel] = cmdname[cmd->c_type][0];
  318.     debdelim[dlevel] = '!';
  319.     if (++dlevel >= dlmax)
  320.         grow_dlevel();
  321.     }
  322. #endif
  323.  
  324. #ifdef macintosh
  325.     SpinPerlCursor(1);
  326. #endif
  327.  
  328.     /* Here is some common optimization */
  329.  
  330.     if (cmdflags & CF_COND) {
  331.     switch (cmdflags & CF_OPTIMIZE) {
  332.  
  333.     case CFT_FALSE:
  334.         retstr = cmd->c_short;
  335.         newsp = -2;
  336.         match = FALSE;
  337.         if (cmdflags & CF_NESURE)
  338.         goto maybe;
  339.         break;
  340.     case CFT_TRUE:
  341.         retstr = cmd->c_short;
  342.         newsp = -2;
  343.         match = TRUE;
  344.         if (cmdflags & CF_EQSURE)
  345.         goto flipmaybe;
  346.         break;
  347.  
  348.     case CFT_REG:
  349.         retstr = STAB_STR(cmd->c_stab);
  350.         newsp = -2;
  351.         match = str_true(retstr);    /* => retstr = retstr, c2 should fix */
  352.         if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
  353.         goto flipmaybe;
  354.         break;
  355.  
  356.     case CFT_ANCHOR:    /* /^pat/ optimization */
  357.         if (multiline) {
  358.         if (*cmd->c_short->str_ptr && !(cmdflags & CF_EQSURE))
  359.             goto scanner;    /* just unanchor it */
  360.         else
  361.             break;        /* must evaluate */
  362.         }
  363.         match = 0;
  364.         goto strop;
  365.  
  366.     case CFT_STROP:        /* string op optimization */
  367.         match = 1;
  368.       strop:
  369.         retstr = STAB_STR(cmd->c_stab);
  370.         newsp = -2;
  371. #ifndef I286
  372.         if (*cmd->c_short->str_ptr == *str_get(retstr) &&
  373.             (match ? retstr->str_cur == cmd->c_slen - 1 :
  374.                      retstr->str_cur >= cmd->c_slen) &&
  375.             bcmp(cmd->c_short->str_ptr, str_get(retstr),
  376.               cmd->c_slen) == 0 ) {
  377.         if (cmdflags & CF_EQSURE) {
  378.             if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  379.             curspat = Nullspat;
  380.             if (leftstab)
  381.                 str_nset(stab_val(leftstab),"",0);
  382.             if (amperstab)
  383.                 str_sset(stab_val(amperstab),cmd->c_short);
  384.             if (rightstab)
  385.                 str_nset(stab_val(rightstab),
  386.                   retstr->str_ptr + cmd->c_slen,
  387.                   retstr->str_cur - cmd->c_slen);
  388.             }
  389.             if (cmd->c_spat)
  390.             lastspat = cmd->c_spat;
  391.             match = !(cmdflags & CF_FIRSTNEG);
  392.             retstr = match ? &str_yes : &str_no;
  393.             goto flipmaybe;
  394.         }
  395.         }
  396.         else if (cmdflags & CF_NESURE) {
  397.         match = cmdflags & CF_FIRSTNEG;
  398.         retstr = match ? &str_yes : &str_no;
  399.         goto flipmaybe;
  400.         }
  401. #else
  402.         {
  403.         char *zap1, *zap2, zap1c, zap2c;
  404.         int  zaplen;
  405.         int lenok;
  406.  
  407.         zap1 = cmd->c_short->str_ptr;
  408.         zap2 = str_get(retstr);
  409.         zap1c = *zap1;
  410.         zap2c = *zap2;
  411.         zaplen = cmd->c_slen;
  412.         if (match)
  413.             lenok = (retstr->str_cur == cmd->c_slen - 1);
  414.         else
  415.             lenok = (retstr->str_cur >= cmd->c_slen);
  416.         if ((zap1c == zap2c) && lenok && (bcmp(zap1, zap2, zaplen) == 0)) {
  417.             if (cmdflags & CF_EQSURE) {
  418.             if (sawampersand &&
  419.               (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
  420.                 curspat = Nullspat;
  421.                 if (leftstab)
  422.                 str_nset(stab_val(leftstab),"",0);
  423.                 if (amperstab)
  424.                 str_sset(stab_val(amperstab),cmd->c_short);
  425.                 if (rightstab)
  426.                 str_nset(stab_val(rightstab),
  427.                      retstr->str_ptr + cmd->c_slen,
  428.                      retstr->str_cur - cmd->c_slen);
  429.             }
  430.             if (cmd->c_spat)
  431.                 lastspat = cmd->c_spat;
  432.              match = !(cmdflags & CF_FIRSTNEG);
  433.             retstr = match ? &str_yes : &str_no;
  434.              goto flipmaybe;
  435.             }
  436.         }
  437.         else if (cmdflags & CF_NESURE) {
  438.             match = cmdflags & CF_FIRSTNEG;
  439.             retstr = match ? &str_yes : &str_no;
  440.             goto flipmaybe;
  441.         }
  442.         }
  443. #endif
  444.         break;            /* must evaluate */
  445.  
  446.     case CFT_SCAN:            /* non-anchored search */
  447.       scanner:
  448.         retstr = STAB_STR(cmd->c_stab);
  449.         newsp = -2;
  450.         if (retstr->str_pok & SP_STUDIED)
  451.         if (screamfirst[cmd->c_short->str_rare] >= 0)
  452.             tmps = screaminstr(retstr, cmd->c_short);
  453.         else
  454.             tmps = Nullch;
  455.         else {
  456.         tmps = str_get(retstr);        /* make sure it's pok */
  457. #ifndef lint
  458.         tmps = fbminstr((unsigned char*)tmps,
  459.             (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
  460. #endif
  461.         }
  462.         if (tmps) {
  463.         if (cmdflags & CF_EQSURE) {
  464.             ++cmd->c_short->str_u.str_useful;
  465.             if (sawampersand) {
  466.             curspat = Nullspat;
  467.             if (leftstab)
  468.                 str_nset(stab_val(leftstab),retstr->str_ptr,
  469.                   tmps - retstr->str_ptr);
  470.             if (amperstab)
  471.                 str_nset(stab_val(amperstab),
  472.                   tmps, cmd->c_short->str_cur);
  473.             if (rightstab)
  474.                 str_nset(stab_val(rightstab),
  475.                   tmps + cmd->c_short->str_cur,
  476.                   retstr->str_cur - (tmps - retstr->str_ptr) -
  477.                 cmd->c_short->str_cur);
  478.             }
  479.             lastspat = cmd->c_spat;
  480.             match = !(cmdflags & CF_FIRSTNEG);
  481.             retstr = match ? &str_yes : &str_no;
  482.             goto flipmaybe;
  483.         }
  484.         else
  485.             hint = tmps;
  486.         }
  487.         else {
  488.         if (cmdflags & CF_NESURE) {
  489.             ++cmd->c_short->str_u.str_useful;
  490.             match = cmdflags & CF_FIRSTNEG;
  491.             retstr = match ? &str_yes : &str_no;
  492.             goto flipmaybe;
  493.         }
  494.         }
  495.         if (--cmd->c_short->str_u.str_useful < 0) {
  496.         cmdflags &= ~CF_OPTIMIZE;
  497.         cmdflags |= CFT_EVAL;    /* never try this optimization again */
  498.         cmd->c_flags = (cmdflags & ~CF_ONCE);
  499.         }
  500.         break;            /* must evaluate */
  501.  
  502.     case CFT_NUMOP:        /* numeric op optimization */
  503.         retstr = STAB_STR(cmd->c_stab);
  504.         newsp = -2;
  505.         switch (cmd->c_slen) {
  506.         case O_EQ:
  507.         if (dowarn) {
  508.             if ((!retstr->str_nok && !looks_like_number(retstr)))
  509.             warn("Possible use of == on string value");
  510.         }
  511.         match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
  512.         break;
  513.         case O_NE:
  514.         match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
  515.         break;
  516.         case O_LT:
  517.         match = (str_gnum(retstr) <  cmd->c_short->str_u.str_nval);
  518.         break;
  519.         case O_LE:
  520.         match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
  521.         break;
  522.         case O_GT:
  523.         match = (str_gnum(retstr) >  cmd->c_short->str_u.str_nval);
  524.         break;
  525.         case O_GE:
  526.         match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
  527.         break;
  528.         }
  529.         if (match) {
  530.         if (cmdflags & CF_EQSURE) {
  531.             retstr = &str_yes;
  532.             goto flipmaybe;
  533.         }
  534.         }
  535.         else if (cmdflags & CF_NESURE) {
  536.         retstr = &str_no;
  537.         goto flipmaybe;
  538.         }
  539.         break;            /* must evaluate */
  540.  
  541.     case CFT_INDGETS:        /* while (<$foo>) */
  542.         last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
  543.         if (!stab_io(last_in_stab))
  544.         stab_io(last_in_stab) = stio_new();
  545.         goto dogets;
  546.     case CFT_GETS:            /* really a while (<file>) */
  547.         last_in_stab = cmd->c_stab;
  548.       dogets:
  549.         fp = stab_io(last_in_stab)->ifp;
  550.         retstr = stab_val(defstab);
  551.         newsp = -2;
  552.       keepgoing:
  553.         if (fp && str_gets(retstr, fp, 0)) {
  554.         if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
  555.             match = FALSE;
  556.         else
  557.             match = TRUE;
  558.         stab_io(last_in_stab)->lines++;
  559.         }
  560.         else if (stab_io(last_in_stab)->flags & IOF_ARGV) {
  561.         if (!fp)
  562.             goto doeval;    /* first time through */
  563.         fp = nextargv(last_in_stab);
  564.         if (fp)
  565.             goto keepgoing;
  566.         (void)do_close(last_in_stab,FALSE);
  567.         stab_io(last_in_stab)->flags |= IOF_START;
  568.         retstr = &str_undef;
  569.         match = FALSE;
  570.         }
  571.         else {
  572.         retstr = &str_undef;
  573.         match = FALSE;
  574.         }
  575.         goto flipmaybe;
  576.     case CFT_EVAL:
  577.         break;
  578.     case CFT_UNFLIP:
  579.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  580.         str_free(tmps_list[tmps_max]);
  581.         tmps_list[tmps_max--] = Nullstr;
  582.         }
  583.         newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
  584.         st = stack->ary_array;    /* possibly reallocated */
  585.         retstr = st[newsp];
  586.         match = str_true(retstr);
  587.         if (cmd->c_expr->arg_type == O_FLIP)    /* undid itself? */
  588.         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  589.         goto maybe;
  590.     case CFT_CHOP:
  591.         retstr = stab_val(cmd->c_stab);
  592.         newsp = -2;
  593.         match = (retstr->str_cur != 0);
  594.         tmps = str_get(retstr);
  595.         tmps += retstr->str_cur - match;
  596.         str_nset(&str_chop,tmps,match);
  597.         *tmps = '\0';
  598.         retstr->str_nok = 0;
  599.         retstr->str_cur = tmps - retstr->str_ptr;
  600.         STABSET(retstr);
  601.         retstr = &str_chop;
  602.         goto flipmaybe;
  603.     case CFT_ARRAY:
  604.         match = cmd->c_short->str_u.str_useful; /* just to get register */
  605.  
  606.         if (match < 0) {        /* first time through here? */
  607.         ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
  608.         aryoptsave = savestack->ary_fill;
  609.         savesptr(&stab_val(cmd->c_stab));
  610.         savelong(&cmd->c_short->str_u.str_useful);
  611.         }
  612.         else {
  613.         ar = stab_xarray(cmd->c_expr[1].arg_ptr.arg_stab);
  614.         if (cmd->c_type != C_WHILE && savestack->ary_fill > firstsave)
  615.             restorelist(firstsave);
  616.         }
  617.  
  618.         if (match >= ar->ary_fill) {    /* we're in LAST, probably */
  619.         if (match < 0 &&        /* er, probably not... */
  620.           savestack->ary_fill > aryoptsave)
  621.             restorelist(aryoptsave);
  622.         retstr = &str_undef;
  623.         cmd->c_short->str_u.str_useful = -1;    /* actually redundant */
  624.         match = FALSE;
  625.         }
  626.         else {
  627.         match++;
  628.         if (!(retstr = ar->ary_array[match]))
  629.             retstr = afetch(ar,match,TRUE);
  630.         stab_val(cmd->c_stab) = retstr;
  631.         cmd->c_short->str_u.str_useful = match;
  632.         match = TRUE;
  633.         }
  634.         newsp = -2;
  635.         goto maybe;
  636.     case CFT_D1:
  637.         break;
  638.     case CFT_D0:
  639.         if (DBsingle->str_u.str_nval != 0)
  640.         break;
  641.         if (DBsignal->str_u.str_nval != 0)
  642.         break;
  643.         if (DBtrace->str_u.str_nval != 0)
  644.         break;
  645.         goto next_cmd;
  646.     }
  647.  
  648.     /* we have tried to make this normal case as abnormal as possible */
  649.  
  650.     doeval:
  651.  
  652. #ifdef macintosh
  653.     SpinPerlCursor(1);
  654. #endif
  655.  
  656.     if (gimme == G_ARRAY) {
  657.         lastretstr = Nullstr;
  658.         lastspbase = sp;
  659.         lastsize = newsp - sp;
  660.         if (lastsize < 0)
  661.         lastsize = 0;
  662.     }
  663.     else
  664.         lastretstr = retstr;
  665.     while (tmps_max > tmps_base) {    /* clean up after last eval */
  666.         str_free(tmps_list[tmps_max]);
  667.         tmps_list[tmps_max--] = Nullstr;
  668.     }
  669.     newsp = eval(cmd->c_expr,
  670.       gimme && (cmdflags & CF_TERM) && cmd->c_type == C_EXPR &&
  671.         !cmd->ucmd.acmd.ac_expr,
  672.       sp);
  673.     st = stack->ary_array;    /* possibly reallocated */
  674.     retstr = st[newsp];
  675.     if (newsp > sp && retstr)
  676.         match = str_true(retstr);
  677.     else
  678.         match = FALSE;
  679.     goto maybe;
  680.  
  681.     /* if flipflop was true, flop it */
  682.  
  683.     flipmaybe:
  684.  
  685. #ifdef macintosh
  686.     SpinPerlCursor(1);
  687. #endif
  688.  
  689.     if (match && cmdflags & CF_FLIP) {
  690.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  691.         str_free(tmps_list[tmps_max]);
  692.         tmps_list[tmps_max--] = Nullstr;
  693.         }
  694.         if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  695.         newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
  696.         cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
  697.         }
  698.         else {
  699.         newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
  700.         if (cmd->c_expr->arg_type == O_FLOP)    /* still toggled? */
  701.             cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
  702.         }
  703.     }
  704.     else if (cmdflags & CF_FLIP) {
  705.         if (cmd->c_expr->arg_type == O_FLOP) {    /* currently toggled? */
  706.         match = TRUE;                /* force on */
  707.         }
  708.     }
  709.  
  710.     /* at this point, match says whether our expression was true */
  711.  
  712.     maybe:
  713.  
  714. #ifdef macintosh
  715.     SpinPerlCursor(1);
  716. #endif
  717.  
  718.     if (cmdflags & CF_INVERT)
  719.         match = !match;
  720.     if (!match)
  721.         goto next_cmd;
  722.     }
  723. #ifdef TAINT
  724.     tainted = 0;    /* modifier doesn't affect regular expression */
  725. #endif
  726.  
  727.     /* now to do the actual command, if any */
  728.  
  729. #ifdef macintosh
  730.     SpinPerlCursor(1);
  731. #endif
  732.  
  733.     switch (cmd->c_type) {
  734.     case C_NULL:
  735.     fatal("panic: cmd_exec");
  736.     case C_EXPR:            /* evaluated for side effects */
  737.     if (cmd->ucmd.acmd.ac_expr) {    /* more to do? */
  738.         if (gimme == G_ARRAY) {
  739.         lastretstr = Nullstr;
  740.         lastspbase = sp;
  741.         lastsize = newsp - sp;
  742.         if (lastsize < 0)
  743.             lastsize = 0;
  744.         }
  745.         else
  746.         lastretstr = retstr;
  747.         while (tmps_max > tmps_base) {    /* clean up after last eval */
  748.         str_free(tmps_list[tmps_max]);
  749.         tmps_list[tmps_max--] = Nullstr;
  750.         }
  751.         newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
  752.         st = stack->ary_array;    /* possibly reallocated */
  753.         retstr = st[newsp];
  754.     }
  755.     break;
  756.     case C_NSWITCH:
  757.     {
  758.         double value = str_gnum(STAB_STR(cmd->c_stab));
  759.  
  760.         match = (int)value;
  761.         if (value < 0.0) {
  762.         if (((double)match) > value)
  763.             --match;        /* was fractional--truncate other way */
  764.         }
  765.     }
  766.  
  767. #ifdef macintosh
  768.     SpinPerlCursor(1);
  769. #endif
  770.  
  771.     goto doswitch;
  772.     case C_CSWITCH:
  773.     match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
  774.       doswitch:
  775.     match -= cmd->ucmd.scmd.sc_offset;
  776.     if (match < 0)
  777.         match = 0;
  778.     else if (match > cmd->ucmd.scmd.sc_max)
  779.         match = cmd->ucmd.scmd.sc_max;
  780.     cmd = cmd->ucmd.scmd.sc_next[match];
  781.     goto tail_recursion_entry;
  782.     case C_NEXT:
  783.     cmd = cmd->ucmd.ccmd.cc_alt;
  784.     goto tail_recursion_entry;
  785.     case C_ELSIF:
  786.     fatal("panic: ELSIF");
  787.     case C_IF:
  788.     oldspat = curspat;
  789.     oldsave = savestack->ary_fill;
  790. #ifdef DEBUGGING
  791.     olddlevel = dlevel;
  792. #endif
  793.     retstr = &str_yes;
  794.     newsp = -2;
  795.     if (cmd->ucmd.ccmd.cc_true) {
  796. #ifdef DEBUGGING
  797.         if (debug) {
  798.         debname[dlevel] = 't';
  799.         debdelim[dlevel] = '_';
  800.         if (++dlevel >= dlmax)
  801.             grow_dlevel();
  802.         }
  803. #endif
  804.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  805.         st = stack->ary_array;    /* possibly reallocated */
  806.         retstr = st[newsp];
  807.     }
  808.     curspat = oldspat;
  809.     if (savestack->ary_fill > oldsave)
  810.         restorelist(oldsave);
  811. #ifdef DEBUGGING
  812.     dlevel = olddlevel;
  813. #endif
  814.     cmd = cmd->ucmd.ccmd.cc_alt;
  815.     goto tail_recursion_entry;
  816.     case C_ELSE:
  817.     oldspat = curspat;
  818.     oldsave = savestack->ary_fill;
  819. #ifdef DEBUGGING
  820.     olddlevel = dlevel;
  821. #endif
  822.     retstr = &str_undef;
  823.     newsp = -2;
  824.     if (cmd->ucmd.ccmd.cc_true) {
  825. #ifdef DEBUGGING
  826.         if (debug) {
  827.         debname[dlevel] = 'e';
  828.         debdelim[dlevel] = '_';
  829.         if (++dlevel >= dlmax)
  830.             grow_dlevel();
  831.         }
  832. #endif
  833.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  834.         st = stack->ary_array;    /* possibly reallocated */
  835.         retstr = st[newsp];
  836.     }
  837.     curspat = oldspat;
  838.     if (savestack->ary_fill > oldsave)
  839.         restorelist(oldsave);
  840. #ifdef DEBUGGING
  841.     dlevel = olddlevel;
  842. #endif
  843.     break;
  844.     case C_BLOCK:
  845.     case C_WHILE:
  846.     if (!(cmdflags & CF_ONCE)) {    /* first time through here? */
  847.         cmdflags |= CF_ONCE;
  848.         if (++loop_ptr >= loop_max) {
  849.         loop_max += 128;
  850.         Renew(loop_stack, loop_max, struct loop);
  851.         }
  852.         loop_stack[loop_ptr].loop_label = cmd->c_label;
  853.         loop_stack[loop_ptr].loop_sp = sp;
  854. #ifdef DEBUGGING
  855.         if (debug & 4) {
  856.         deb("(Pushing label #%d %s)\n",
  857.           loop_ptr, cmd->c_label ? cmd->c_label : "");
  858.         }
  859. #endif
  860.     }
  861. #ifdef JMPCLOBBER
  862.     cmdparm = cmd;
  863. #endif
  864.     match = setjmp(loop_stack[loop_ptr].loop_env);
  865.     if (match) {
  866.         st = stack->ary_array;    /* possibly reallocated */
  867. #ifdef JMPCLOBBER
  868.         cmd = cmdparm;
  869.         cmdflags = cmd->c_flags|CF_ONCE;
  870.         go_to = goto_targ;
  871. #endif
  872.         if (savestack->ary_fill > oldsave)
  873.         restorelist(oldsave);
  874.         switch (match) {
  875.         default:
  876.         fatal("longjmp returned bad value (%d)",match);
  877.         case O_LAST:
  878.         if (lastretstr) {
  879.             retstr = lastretstr;
  880.             newsp = -2;
  881.         }
  882.         else {
  883.             newsp = sp + lastsize;
  884.             retstr = st[newsp];
  885.         }
  886.         curspat = oldspat;
  887.         goto next_cmd;
  888.         case O_NEXT:
  889. #ifdef JMPCLOBBER
  890.         newsp = -2;
  891.         retstr = &str_undef;
  892. #endif
  893.         goto next_iter;
  894.         case O_REDO:
  895. #ifdef DEBUGGING
  896.         dlevel = olddlevel;
  897. #endif
  898. #ifdef JMPCLOBBER
  899.         newsp = -2;
  900.         retstr = &str_undef;
  901. #endif
  902.         goto doit;
  903.         }
  904.     }
  905.     oldspat = curspat;
  906.     oldsave = savestack->ary_fill;
  907. #ifdef DEBUGGING
  908.     olddlevel = dlevel;
  909. #endif
  910.     doit:
  911.     if (cmd->ucmd.ccmd.cc_true) {
  912. #ifdef DEBUGGING
  913.         if (debug) {
  914.         debname[dlevel] = 't';
  915.         debdelim[dlevel] = '_';
  916.         if (++dlevel >= dlmax)
  917.             grow_dlevel();
  918.         }
  919. #endif
  920.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme && (cmdflags & CF_TERM),sp);
  921.         st = stack->ary_array;    /* possibly reallocated */
  922.         retstr = st[newsp];
  923.     }
  924.     /* actually, this spot is rarely reached anymore since the above
  925.      * cmd_exec() returns through longjmp().  Hooray for structure.
  926.      */
  927.       next_iter:
  928. #ifdef DEBUGGING
  929.     dlevel = olddlevel;
  930. #endif
  931.     if (cmd->ucmd.ccmd.cc_alt) {
  932. #ifdef DEBUGGING
  933.         if (debug) {
  934.         debname[dlevel] = 'a';
  935.         debdelim[dlevel] = '_';
  936.         if (++dlevel >= dlmax)
  937.             grow_dlevel();
  938.         }
  939. #endif
  940.         newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme && (cmdflags & CF_TERM),sp);
  941.         st = stack->ary_array;    /* possibly reallocated */
  942.         retstr = st[newsp];
  943.     }
  944.       finish_while:
  945.     curspat = oldspat;
  946.     if (savestack->ary_fill > oldsave) {
  947.         if (cmdflags & CF_TERM) {
  948.         for (match = sp + 1; match <= newsp; match++)
  949.             st[match] = str_mortal(st[match]);
  950.         retstr = st[newsp];
  951.         }
  952.         restorelist(oldsave);
  953.     }
  954. #ifdef DEBUGGING
  955.     dlevel = olddlevel - 1;
  956. #endif
  957.     if (cmd->c_type != C_BLOCK)
  958.         goto until_loop;    /* go back and evaluate conditional again */
  959.     }
  960.     if (cmdflags & CF_LOOP) {
  961.     cmdflags |= CF_COND;        /* now test the condition */
  962. #ifdef DEBUGGING
  963.     dlevel = entdlevel;
  964. #endif
  965.     goto until_loop;
  966.     }
  967.   next_cmd:
  968.  
  969. #ifdef macintosh
  970.     SpinPerlCursor(1);
  971. #endif
  972.  
  973.     if (cmdflags & CF_ONCE) {
  974. #ifdef DEBUGGING
  975.     if (debug & 4) {
  976.         tmps = loop_stack[loop_ptr].loop_label;
  977.         deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
  978.     }
  979. #endif
  980.     loop_ptr--;
  981.     if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY &&
  982.       savestack->ary_fill > aryoptsave)
  983.         restorelist(aryoptsave);
  984.     }
  985.     cmd = cmd->c_next;
  986.     goto tail_recursion_entry;
  987. }
  988.  
  989. #ifdef DEBUGGING
  990. #  ifndef I_VARARGS
  991. /*VARARGS1*/
  992. deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
  993. char *pat;
  994. {
  995.     register int i;
  996.  
  997.     fprintf(stderr,"%-4ld",(long)curcmd->c_line);
  998.     for (i=0; i<dlevel; i++)
  999.     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  1000.     fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
  1001. }
  1002. #  else
  1003. /*VARARGS1*/
  1004. deb(va_alist)
  1005. va_dcl
  1006. {
  1007.     va_list args;
  1008.     char *pat;
  1009.     register int i;
  1010.  
  1011.     va_start(args);
  1012.     fprintf(stderr,"%-4ld",(long)curcmd->c_line);
  1013.     for (i=0; i<dlevel; i++)
  1014.     fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
  1015.  
  1016.     pat = va_arg(args, char *);
  1017.     (void) vfprintf(stderr,pat,args);
  1018.     va_end( args );
  1019. }
  1020. #  endif
  1021. #endif
  1022.  
  1023. copyopt(cmd,which)
  1024. register CMD *cmd;
  1025. register CMD *which;
  1026. {
  1027.     cmd->c_flags &= CF_ONCE|CF_COND|CF_LOOP;
  1028.     cmd->c_flags |= which->c_flags;
  1029.     cmd->c_short = which->c_short;
  1030.     cmd->c_slen = which->c_slen;
  1031.     cmd->c_stab = which->c_stab;
  1032.     return cmd->c_flags;
  1033. }
  1034.  
  1035. ARRAY *
  1036. saveary(stab)
  1037. STAB *stab;
  1038. {
  1039.     register STR *str;
  1040.  
  1041.     str = Str_new(10,0);
  1042.     str->str_state = SS_SARY;
  1043.     str->str_u.str_stab = stab;
  1044.     if (str->str_ptr) {
  1045.     Safefree(str->str_ptr);
  1046.     str->str_ptr = Nullch;
  1047.     str->str_len = 0;
  1048.     }
  1049.     str->str_ptr = (char*)stab_array(stab);
  1050.     (void)apush(savestack,str); /* save array ptr */
  1051.     stab_xarray(stab) = Null(ARRAY*);
  1052.     return stab_xarray(aadd(stab));
  1053. }
  1054.  
  1055. HASH *
  1056. savehash(stab)
  1057. STAB *stab;
  1058. {
  1059.     register STR *str;
  1060.  
  1061.     str = Str_new(11,0);
  1062.     str->str_state = SS_SHASH;
  1063.     str->str_u.str_stab = stab;
  1064.     if (str->str_ptr) {
  1065.     Safefree(str->str_ptr);
  1066.     str->str_ptr = Nullch;
  1067.     str->str_len = 0;
  1068.     }
  1069.     str->str_ptr = (char*)stab_hash(stab);
  1070.     (void)apush(savestack,str); /* save hash ptr */
  1071.     stab_xhash(stab) = Null(HASH*);
  1072.     return stab_xhash(hadd(stab));
  1073. }
  1074.  
  1075. void
  1076. saveitem(item)
  1077. register STR *item;
  1078. {
  1079.     register STR *str;
  1080.  
  1081.     (void)apush(savestack,item);        /* remember the pointer */
  1082.     str = Str_new(12,0);
  1083.     str_sset(str,item);
  1084.     (void)apush(savestack,str);            /* remember the value */
  1085. }
  1086.  
  1087. void
  1088. saveint(intp)
  1089. int *intp;
  1090. {
  1091.     register STR *str;
  1092.  
  1093.     str = Str_new(13,0);
  1094.     str->str_state = SS_SINT;
  1095.     str->str_u.str_useful = (long)*intp;    /* remember value */
  1096.     if (str->str_ptr) {
  1097.     Safefree(str->str_ptr);
  1098.     str->str_len = 0;
  1099.     }
  1100.     str->str_ptr = (char*)intp;        /* remember pointer */
  1101.     (void)apush(savestack,str);
  1102. }
  1103.  
  1104. void
  1105. savelong(longp)
  1106. long *longp;
  1107. {
  1108.     register STR *str;
  1109.  
  1110.     str = Str_new(14,0);
  1111.     str->str_state = SS_SLONG;
  1112.     str->str_u.str_useful = *longp;        /* remember value */
  1113.     if (str->str_ptr) {
  1114.     Safefree(str->str_ptr);
  1115.     str->str_len = 0;
  1116.     }
  1117.     str->str_ptr = (char*)longp;        /* remember pointer */
  1118.     (void)apush(savestack,str);
  1119. }
  1120.  
  1121. void
  1122. savesptr(sptr)
  1123. STR **sptr;
  1124. {
  1125.     register STR *str;
  1126.  
  1127.     str = Str_new(15,0);
  1128.     str->str_state = SS_SSTRP;
  1129.     str->str_magic = *sptr;        /* remember value */
  1130.     if (str->str_ptr) {
  1131.     Safefree(str->str_ptr);
  1132.     str->str_len = 0;
  1133.     }
  1134.     str->str_ptr = (char*)sptr;        /* remember pointer */
  1135.     (void)apush(savestack,str);
  1136. }
  1137.  
  1138. void
  1139. savenostab(stab)
  1140. STAB *stab;
  1141. {
  1142.     register STR *str;
  1143.  
  1144.     str = Str_new(16,0);
  1145.     str->str_state = SS_SNSTAB;
  1146.     str->str_magic = (STR*)stab;    /* remember which stab to free */
  1147.     (void)apush(savestack,str);
  1148. }
  1149.  
  1150. void
  1151. savehptr(hptr)
  1152. HASH **hptr;
  1153. {
  1154.     register STR *str;
  1155.  
  1156.     str = Str_new(17,0);
  1157.     str->str_state = SS_SHPTR;
  1158.     str->str_u.str_hash = *hptr;    /* remember value */
  1159.     if (str->str_ptr) {
  1160.     Safefree(str->str_ptr);
  1161.     str->str_len = 0;
  1162.     }
  1163.     str->str_ptr = (char*)hptr;        /* remember pointer */
  1164.     (void)apush(savestack,str);
  1165. }
  1166.  
  1167. void
  1168. saveaptr(aptr)
  1169. ARRAY **aptr;
  1170. {
  1171.     register STR *str;
  1172.  
  1173.     str = Str_new(17,0);
  1174.     str->str_state = SS_SAPTR;
  1175.     str->str_u.str_array = *aptr;    /* remember value */
  1176.     if (str->str_ptr) {
  1177.     Safefree(str->str_ptr);
  1178.     str->str_len = 0;
  1179.     }
  1180.     str->str_ptr = (char*)aptr;        /* remember pointer */
  1181.     (void)apush(savestack,str);
  1182. }
  1183.  
  1184. void
  1185. savelist(sarg,maxsarg)
  1186. register STR **sarg;
  1187. int maxsarg;
  1188. {
  1189.     register STR *str;
  1190.     register int i;
  1191.  
  1192.     for (i = 1; i <= maxsarg; i++) {
  1193.     (void)apush(savestack,sarg[i]);        /* remember the pointer */
  1194.     str = Str_new(18,0);
  1195.     str_sset(str,sarg[i]);
  1196.     (void)apush(savestack,str);            /* remember the value */
  1197.     sarg[i]->str_u.str_useful = -1;
  1198.     }
  1199. }
  1200.  
  1201. void
  1202. restorelist(base)
  1203. int base;
  1204. {
  1205.     register STR *str;
  1206.     register STR *value;
  1207.     register STAB *stab;
  1208.  
  1209.     if (base < -1)
  1210.     fatal("panic: corrupt saved stack index");
  1211.     while (savestack->ary_fill > base) {
  1212.     value = apop(savestack);
  1213.     switch (value->str_state) {
  1214.     case SS_NORM:                /* normal string */
  1215.     case SS_INCR:
  1216.         str = apop(savestack);
  1217.         str_replace(str,value);
  1218.         STABSET(str);
  1219.         break;
  1220.     case SS_SARY:                /* array reference */
  1221.         stab = value->str_u.str_stab;
  1222.         afree(stab_xarray(stab));
  1223.         stab_xarray(stab) = (ARRAY*)value->str_ptr;
  1224.         value->str_ptr = Nullch;
  1225.         str_free(value);
  1226.         break;
  1227.     case SS_SHASH:                /* hash reference */
  1228.         stab = value->str_u.str_stab;
  1229. #ifndef macintosh
  1230.         (void)hfree(stab_xhash(stab), FALSE);
  1231. #else
  1232.         hfree(stab_xhash(stab), FALSE);
  1233. #endif
  1234.         stab_xhash(stab) = (HASH*)value->str_ptr;
  1235.         value->str_ptr = Nullch;
  1236.         str_free(value);
  1237.         break;
  1238.     case SS_SINT:                /* int reference */
  1239.         *((int*)value->str_ptr) = (int)value->str_u.str_useful;
  1240.         value->str_ptr = Nullch;
  1241.         str_free(value);
  1242.         break;
  1243.     case SS_SLONG:                /* long reference */
  1244.         *((long*)value->str_ptr) = value->str_u.str_useful;
  1245.         value->str_ptr = Nullch;
  1246.         str_free(value);
  1247.         break;
  1248.     case SS_SSTRP:                /* STR* reference */
  1249.         *((STR**)value->str_ptr) = value->str_magic;
  1250.         value->str_magic = Nullstr;
  1251.         value->str_ptr = Nullch;
  1252.         str_free(value);
  1253.         break;
  1254.     case SS_SHPTR:                /* HASH* reference */
  1255.         *((HASH**)value->str_ptr) = value->str_u.str_hash;
  1256.         value->str_ptr = Nullch;
  1257.         str_free(value);
  1258.         break;
  1259.     case SS_SAPTR:                /* ARRAY* reference */
  1260.         *((ARRAY**)value->str_ptr) = value->str_u.str_array;
  1261.         value->str_ptr = Nullch;
  1262.         str_free(value);
  1263.         break;
  1264.     case SS_SNSTAB:
  1265.         stab = (STAB*)value->str_magic;
  1266.         value->str_magic = Nullstr;
  1267. #ifndef macintosh
  1268.         (void)stab_clear(stab);
  1269. #else
  1270.         stab_clear(stab);
  1271. #endif
  1272.         str_free(value);
  1273.         break;
  1274.     case SS_SCSV:                /* callsave structure */
  1275.         {
  1276.         CSV *csv = (CSV*) value->str_ptr;
  1277.  
  1278.         curcmd = csv->curcmd;
  1279.         curcsv = csv->curcsv;
  1280.         csv->sub->depth = csv->depth;
  1281.         if (csv->hasargs) {        /* put back old @_ */
  1282.             afree(csv->argarray);
  1283.             stab_xarray(defstab) = csv->savearray;
  1284.         }
  1285.         str_free(value);
  1286.         }
  1287.         break;
  1288.     default:
  1289.         fatal("panic: restorelist inconsistency");
  1290.     }
  1291.     }
  1292. }
  1293.  
  1294. #ifdef DEBUGGING
  1295. void
  1296. grow_dlevel()
  1297. {
  1298.     dlmax += 128;
  1299.     Renew(debname, dlmax, char);
  1300.     Renew(debdelim, dlmax, char);
  1301. }
  1302. #endif
  1303.